package org.za.communication.core.codec.decoder;

import java.util.ArrayList;
import java.util.List;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.za.communication.core.util.DESPlus;

public class DataSegmentationDecoder extends CumulativeProtocolDecoder {

	private final static Logger log = LoggerFactory
			.getLogger(DataSegmentationDecoder.class);

	private byte[] head;
	private List<Integer> decryptIdList = new ArrayList<Integer>();

	public List<Integer> getDecryptIdList() {
		return decryptIdList;
	}

	public void setDecryptIdList(List<Integer> decryptIdList) {
		this.decryptIdList = decryptIdList;
	}

	public byte[] getHead() {
		return head;
	}

	public void setHead(byte[] head) {
		this.head = head;
	}

	@Override
	protected boolean doDecode(IoSession session, IoBuffer in,
			ProtocolDecoderOutput out) throws Exception {
		if (head == null || head.length == 0) {
			throw new Exception("no head data");
		}

		while (in.hasRemaining()) {
			byte[] tempHead = new byte[head.length];
			int position = in.position();
			tempHead[0] = in.get();
			if (tempHead[0] == head[0]) {
				if (in.remaining() >= head.length - 1) {
					in.mark();
					for (int i = 1; i < head.length; i++) {
						tempHead[i] = in.get();
						if (tempHead[i] == head[i]) {

						} else {
							in.reset();
							return true;
						}
					}
				} else {
					in.position(position);
					return false;
				}

				if (in.remaining() >= 4) {
					int length = in.getInt();
					if (in.remaining() >= length) {
						IoBuffer buf = in.getSlice(length);

						int id = buf.getUnsignedShort();

						if (decryptIdList.contains(id)) {
							byte[] key = new byte[4];

							buf.get(key);
							int l = buf.limit() - buf.position();
							byte[] data = new byte[l];
							buf.get(data);
							DESPlus des = new DESPlus(new String(key));
							data = des.decrypt(data);

							IoBuffer buffOut = IoBuffer
									.allocate(6 + data.length);
							buffOut.putUnsignedShort(id);
							buffOut.put(key);
							buffOut.put(data);
							buffOut.flip();

							out.write(buffOut);

						} else {
							IoBuffer buffOut = IoBuffer.allocate(10)
									.setAutoExpand(true);
							buf.position(0);
							buffOut = buf.slice();

							out.write(buffOut);

						}

						if (in.remaining() > 0) {
							return true;
						}
					} else {
						in.position(position);
						return false;
					}

				} else {
					in.position(position);
					return false;
				}
			}

		}
		return false;
	}
}
